package main

import (
	"fmt"
	"sync"
)

/*
Go语言包中的sync包提供了两种锁类型：sync.Mutex和sync.RWMutex。Mutex是最简单
的一种锁类型，同时也比较暴力，当一个goroutine获得了Mutex后，其他goroutine就只能乖乖等
到这个goroutine释放该Mutex。RWMutex相对友好些，是经典的单写多读模型。在读锁占用的情
况下，会阻止写，但不阻止读，也就是多个goroutine可同时获取读锁（调用RLock()方法；而写
锁（调用Lock()方法）会阻止任何其他goroutine（无论读和写）进来，整个锁相当于由该goroutine
独占。

对于这两种锁类型，任何一个Lock()或RLock()均需要保证对应有Unlock()或RUnlock()
调用与之对应，否则可能导致等待该锁的所有goroutine处于饥饿状态，甚至可能导致死锁。锁的
典型使用模式如下：
var l sync.Mutex
func foo() {
 l.Lock()
 defer l.Unlock()
 //...
}
*/

var lock sync.Mutex

//WaitGroup对象不是一个引用类型，在通过函数传值的时候需要使用地址
func syncAdd(x *int, wg *sync.WaitGroup) {
	lock.Lock()
	defer wg.Done()
	defer lock.Unlock()
	*x += 1
}

func main30() {
	x := 0
	wg := sync.WaitGroup{} //相当于java中的门闩
	wg.Add(1000)
	for i := 0; i < 1000; i++ {
		go syncAdd(&x, &wg)
	}
	wg.Wait() // 等等所有goroutine运行完毕
	fmt.Println(x)
}
